<template>
  <div class="input-number"
       :class="[
      size ? 'el-input-number--' + size : '',
      { 'is-disabled': disabled },
      { 'is-without-controls': !controls}
    ]"
  >
    <span
      v-if="controls"
      class="input-number__decrease"
      :class="{'is-disabled': minDisabled}"
      @click="decrease"
    >
     -
    </span>
    <span
      v-if="controls"
      class="input-number__increase"
      :class="{'is-disabled': maxDisabled}"
      @click="increase"
    >
      +
    </span>
    <input-text  class="input-text"
      :value="currentValue"
      @keydown.up.native.prevent="increase"
      @keydown.down.native.prevent="decrease"
      @blur="handleBlur"
      @input="debounceHandleInput"
      :disabled="disabled"
      :size="size"
      :max="max"
      :min="min"
      ref="input"
    >
    </input-text>
  </div>
</template>
<script>
  import _ from 'lodash'
  import InputText from '../../../libs/dynamic-form/input-types/InputText.vue'
  import {once, on} from '../utils/dom'

  export default {
    directives: {
      repeatClick: {
        bind (el, binding, vnode) {
          let interval = null
          let startTime
          const handler = () => vnode.context[binding.expression].apply()
          const clear = () => {
            if (new Date() - startTime < 100) {
              handler()
            }
            clearInterval(interval)
            interval = null
          }

          on(el, 'mousedown', () => {
            startTime = new Date()
            once(document, 'mouseup', clear)
            clearInterval(interval)
            interval = setInterval(handler, 100)
          })
        }
      }
    },
    components: {
      InputText
    },
    props: {
      step: {
        type: Number,
        default: 1
      },
      max: {
        type: Number,
        default: 100
      },
      min: {
        type: Number,
        default: 0
      },
      value: {
        default: 0
      },
      disabled: Boolean,
      size: String,
      controls: {
        type: Boolean,
        default: true
      },
      debounce: {
        type: Number,
        default: 300
      }
    },
    data () {
      return {
        currentValue: 0
      }
    },
    watch: {
      value: {
        immediate: true,
        handler (value) {
          let newVal = Number(value)
          if (isNaN(newVal)) return
          if (newVal >= this.max) newVal = this.max
          if (newVal <= this.min) newVal = this.min
          this.currentValue = newVal
          this.$emit('input', newVal)
        }
      }
    },
    computed: {
      minDisabled () {
        return this._decrease(this.value, this.step) < this.min
      },
      maxDisabled () {
        return this._increase(this.value, this.step) > this.max
      },
      precision () {
        const {value, step, getPrecision} = this
        return Math.max(getPrecision(value), getPrecision(step))
      }
    },
    methods: {
      toPrecision (num, precision) {
        if (precision === undefined) precision = this.precision
        return parseFloat(parseFloat(Number(num).toFixed(precision)))
      },
      getPrecision (value) {
        const valueString = value.toString()
        const dotPosition = valueString.indexOf('.')
        let precision = 0
        if (dotPosition !== -1) {
          precision = valueString.length - dotPosition - 1
        }
        return precision
      },
      _increase (val, step) {
        if (typeof val !== 'number') return this.currentValue

        const precisionFactor = Math.pow(10, this.precision)

        return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor)
      },
      _decrease (val, step) {
        if (typeof val !== 'number') return this.currentValue

        const precisionFactor = Math.pow(10, this.precision)

        return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor)
      },
      increase () {
        if (this.disabled || this.maxDisabled) return
        const value = this.value || 0
        const newVal = this._increase(value, this.step)
        if (newVal > this.max) return
        this.setCurrentValue(newVal)
      },
      decrease () {
        if (this.disabled || this.minDisabled) return
        const value = this.value || 0
        const newVal = this._decrease(value, this.step)
        if (newVal < this.min) return
        this.setCurrentValue(newVal)
      },
      handleBlur () {
        this.$refs.input.setCurrentValue(this.currentValue)
      },
      setCurrentValue (newVal) {
        const oldVal = this.currentValue
        if (newVal >= this.max) newVal = this.max
        if (newVal <= this.min) newVal = this.min
//        if (oldVal === newVal) {
//          console.log(this)
//          this.$refs.input.setCurrentValue(this.currentValue)
//          this.currentValue = newVal
//          return
//        }
        this.currentValue = newVal
        this.$emit('change', newVal, oldVal)
        this.$emit('input', newVal)
      },
      handleInput (value) {
        if (value === '') {
          return
        }
        const newVal = Number(value)
        if (!isNaN(newVal)) {
          this.setCurrentValue(newVal)
        } else {
          this.setCurrentValue(this.currentValue)
        }
      }
    },
    created () {
      this.debounceHandleInput = _.debounce(value => {
        this.handleInput(value)
      }, this.debounce)
    }
  }
</script>

<style>
  .input-number{
    display: inline-block;
    width: 180px;
    position: relative;
  }
 .input-number__decrease{
   right: 37px;
   height: auto;
   border-left: 1px solid #bfcbd9;
   width: 36px;
   line-height: 34px;
   top: 1px;
   text-align: center;
   color: #97a8be;
   cursor: pointer;
   position: absolute;
   z-index: 1;
 }
  .input-number__increase {
    right: 0;
    height: auto;
    border-left: 1px solid #bfcbd9;
    width: 36px;
    line-height: 34px;
    top: 1px;
    text-align: center;
    color: #97a8be;
    cursor: pointer;
    position: absolute;
    z-index: 1;
  }
  .input-text {
    display: block;
    position: relative;
    font-size: 14px;
    width: 100%;
    padding: 6px;
  }

</style>

